package org.hidaron.asyncdownloader.download.queue;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.hidaron.asyncdownloader.download.DownloadStatus;
import org.hidaron.asyncdownloader.download.Downloader;

import android.util.Log;

/**
 * 
 * @author hidaron <hidaron@163.com>
 * 
 */
public class DownloaderTaskQueue implements TaskQueue {
	public static final String TAG = DownloaderTaskQueue.class.getSimpleName();
	public static final int MAX_NUM = 3;

	private List<Downloader> taskQueue;

	public DownloaderTaskQueue() {
		taskQueue = Collections.synchronizedList(new LinkedList<Downloader>());
	}

	@Override
	public boolean add(Downloader downloader) {
		if (taskQueue.add(downloader)) {
			Log.d(TAG, "queue length " + taskQueue.size());
			notifyTask(TaskQueue.TASK_ACTION_ADD);
			return true;
		}
		return false;
	}

	@Override
	public boolean update(Downloader downloader) {
		if (isRunningLimit()) {
			downloader.setDownloadStatus(DownloadStatus.WAITING);
			return false;
		}
		downloader.redownload();
		return true;
	}

	@Override
	public boolean remove(Downloader downloader) {
		if (taskQueue.remove(downloader)) {
			notifyTask(TaskQueue.TASK_ACTION_REMOVE);
			return true;
		}
		return false;
	}

	@Override
	public void removeAll() {
		if (taskQueue.size() > 0) {
			notifyTask(TaskQueue.TASK_ACTION_REMOVE_ALL);
			taskQueue.removeAll(taskQueue);
		}
	}

	public Downloader get(int position) {
		return taskQueue.get(position);
	}

	private Downloader getTheLast() {
		if (taskQueue.size() == 0) {
			return null;
		}
		return taskQueue.get(taskQueue.size() - 1);
	}

	@Override
	public boolean contains(Downloader downloader) {
		return taskQueue.contains(downloader);
	}

	private int getStatusCount(DownloadStatus status) {
		int count = 0;
		for (Downloader downloader : taskQueue) {
			if (downloader.getInfo().getStatus() == status) {
				++count;
			}
		}
		return count;
	}

	private Downloader getTheFirstOf(DownloadStatus status) {
		if (taskQueue.size() > 0) {
			for (Downloader downloader : taskQueue) {
				if (downloader.getInfo().getStatus() == status) {
					return downloader;
				}
			}
		}
		return null;
	}

	@Override
	public int getLimit() {
		return MAX_NUM;
	}

	private boolean isRunningLimit() {
		return getStatusCount(DownloadStatus.DOWNLOADING) >= getLimit();
	}

	public synchronized void notifyTask(int taskType) {
		Downloader downloader;
		switch (taskType) {
		case TaskQueue.TASK_ACTION_ADD:
			downloader = getTheLast();
			if (isRunningLimit()) {
				downloader.setDownloadStatus(DownloadStatus.WAITING);
				return;
			}
			downloader.download();
			break;
		case TaskQueue.TASK_ACTION_REMOVE:
			downloader = getTheFirstOf(DownloadStatus.WAITING);
			if (downloader != null) {
				downloader.download();
			}
			break;
		case TaskQueue.TASK_ACTION_REMOVE_ALL:
			if (taskQueue.size() > 0) {
				for (Downloader d : taskQueue) {
					if (d.getInfo().getStatus() == DownloadStatus.DOWNLOADING)
						d.cancel();
				}
			}
			break;
		}
	}
}
